import shutil

from django.shortcuts import render, redirect

import AppManager.Mysql
import HostManager.SSH
from OpManager import settings
from AppManager import views as AM_views
from HostManager import views as HM_views
from Logs import views as Logs_views

InstalledDict = {}
FileDIr = "HostSetting/InstallScript/"
FileName = {
    "jdk": "install_jdk.sh",
    "mysql": "install_mysql.sh",
    "nginx": "install_nginx.sh",
    "redis": "install_redis.sh",
    "tomcat": "install_tomcat.sh",
    "ZabbixAgentd": "install_ZabbixAgentd.sh",
    "ZabbixProxy": "install_ZabbixProxy.sh"
}
FileData = {
    "jdk": "",
    "mysql": "",
    "nginx": "",
    "redis": "",
    "tomcat": "",
    "ZabbixAgentd": "",
    "ZabbixProxy": ""
}
AppIndex = {
    "jdk": 7,
    "mysql": 9,
    "nginx": 11,
    "redis": 15,
    "tomcat": 13,
    "ZabbixAgentd": "",
    "ZabbixProxy": ""
}
AppConfig = {}


# 主机设置主页
@settings.auth(AuthType="HostSetting", AuthNum=1)
def HostSetting(requests):
    if requests.method == 'POST':
        sql = "UPDATE `hostsetting` SET `sourceURL` = '%s', `TmpDir` = '%s', `InstallDir` = '%s', " \
              "`ScriptType` = '%s', `ScriptRun` = '%s' WHERE `Plan` = '1';" % (
                  requests.POST['sourceURL'], requests.POST['TmpDir'], requests.POST['InstallDir'],
                  requests.POST['ScriptType'], requests.POST['ScriptRun'])
        print(sql)
        AppManager.Mysql.MysqlPool(sql, 0)
        return redirect("/hostsetting")
    LoadConfig()
    context = {
        "setting": AppConfig
    }
    return render(requests, 'HostSetting.html', context)


# 部署应用主页
@settings.auth(AuthType="HostSetting", AuthNum=2)
def InstallApp(requests):
    if requests.method == 'POST':
        DataBody = requests.POST.copy()
        hostname = DataBody["host"]
        DataBody.pop("host")

        # 获取主机的信息
        sql = "SELECT * FROM `host` where hostname='%s'" % hostname
        host = AppManager.Mysql.MysqlPool(sql, 1)
        sql = "SELECT * FROM `host_dev` WHERE hostname LIKE '%s'" % hostname
        hostdev = AppManager.Mysql.MysqlPool(sql, 1)
        HostData = {
            "host": host["ip"],
            "port": host["ssh_port"],
            "username": hostdev["Suser"],
            "password": hostdev["Spasswd"]
        }
        InstallingApp = ""
        # 遍历需要安装的软件进行生成脚本
        for appname in DataBody.keys():
            # 记录一共安装哪些应用，用于记录日志
            InstallingApp += appname + ","
            InstalledDict[hostname][appname] = "正在生成脚本..."
            print("开始生成", appname)
            try:
                ParamDict = {
                    "InstallDir": AppConfig["InstallDir"],
                    "FileName": AppConfig[appname + "_version"],
                    "sourceURL": AppConfig["sourceURL"]
                }
                replaceScript(appname, ParamDict)
                print("脚本生成完成")
            except KeyError:
                print("KeyError:" + appname)
                InstalledDict[hostname][appname] = "脚本生成失败：暂不支持该应用"

        # 记录安装日志
        Logs_views.log("发起了部署应用：" + InstallingApp, user=requests.COOKIES.get('user'))

        # 将脚本发送到目标服务器
        Ures = HM_views.UploadSftp(HostData, "HostSetting/InstallScript/tmp", AppConfig["TmpDir"])
        if Ures:
            print("已将文件发送至", AppConfig["TmpDir"])
            for appname in DataBody.keys():
                if not InstalledDict[hostname][appname] == "脚本生成失败：暂不支持该应用":
                    InstalledDict[hostname][appname] = "正在安装..."
                    StartInstall(HostData, appname)
                    InstalledDict[hostname][appname] = "请更新"
        else:
            print("文件发送失败", AppConfig["TmpDir"])
            for appname in DataBody.keys():
                # 遍历需要安装的软件
                InstalledDict[hostname][appname] = "脚本发送失败"
        return redirect("/addapp")
    else:
        context = {
            "AppList": FileName,
            "Installed": InstalledDict
        }
        return render(requests, 'InstallApp.html', context)


# 配置管理主页
@settings.auth(AuthType="HostSetting", AuthNum=3)
def HostConfig(requests):
    if requests.method == 'POST':
        tmpTuple = (requests.POST['jdk_version'], requests.POST['mysql_version'], requests.POST['nginx_version'],
                    requests.POST['tomcat_version'], requests.POST['redis_version'])
        sql = "UPDATE `opmanager`.`hostsetting` SET `jdk_version`='%s',`mysql_version`='%s',`nginx_version`='%s'," \
              " `tomcat_version` = '%s', `redis_version` = '%s' WHERE `Plan` = '1';" % tmpTuple
        AppManager.Mysql.MysqlPool(sql, 0)
        update = "jdk_version:%s,mysql_version:%s,nginx_version:%s,tomcat_version:%s,redis_version:%s" % tmpTuple
        Logs_views.log("更新了：" + update, user=requests.COOKIES.get('user'))
        return redirect("/config")
    LoadConfig()
    context = {
        "setting": AppConfig
    }
    return render(requests, 'hostconfig.html', context)


# 立即更新按钮
@settings.auth(AuthType="HostSetting", AuthNum=2)
def GetInstalled(requests):
    getInstalledList()
    LoadScript()
    return redirect("/addapp")


# 后台获取服务器是否已安装应用
def getInstalledList():
    global InstalledDict
    commands = []
    commandDict = {}
    sql = "SELECT * FROM `host`"
    hostlist = AppManager.Mysql.MysqlPool(sql, 99)
    for filename in FileName:
        commandDict[filename] = "cat " + AppConfig["InstallDir"] + "/Installed/" + filename
        commands.append(commandDict[filename])
    for host in hostlist:
        try:
            sql = "SELECT * FROM `host_dev` WHERE hostname LIKE '{0}'".format(host["hostname"])
            hostdev = AppManager.Mysql.MysqlPool(sql, 1)
            res = HostManager.SSH.SshComm(host["ip"], host["ssh_port"], hostdev["Suser"], hostdev["Spasswd"], commands)
            InstalledDict[host["hostname"]] = {}
            for filename in FileName:
                InstalledDict[host["hostname"]][filename] = res[commandDict[filename]]["stdout"]
        except Exception as e:
            print("获取" + host["hostname"] + ":" + host["ip"] + "已安装列表出现异常")
            print("getInstalledList:" + str(type(e)) + ":" + str(e))


# 读取脚本到内存
def LoadScript():
    global FileData
    for appname, filename in FileName.items():
        Path = FileDIr + filename
        with open(Path, 'r', encoding='utf-8') as ScriptData:
            FileData[appname] = ScriptData.read()
    shutil.rmtree(FileDIr + "tmp/res")
    shutil.copytree(FileDIr + "res", FileDIr + "tmp/res")


# 对指定脚本的内存中的数据使用字典的方式进行遍历替换并写入tmp
def replaceScript(appname, ParamDict: dict):
    global FileData
    for ParamName, Param in ParamDict.items():
        ParamName = "{[{" + ParamName + "}]}"
        FileData[appname] = FileData[appname].replace(ParamName, Param)
    with open(FileDIr + "tmp/" + FileName[appname], 'w', encoding='utf-8') as tmpfile:
        tmpfile.write(FileData[appname])


# 将应用配置读取到内存中
def LoadConfig():
    global AppConfig
    sql = "SELECT * FROM `hostsetting` where Plan='1'"
    res = AppManager.Mysql.MysqlPool(sql, 1)
    AppConfig = res


def StartInstall(HostData, AppName):
    tmpStr = "cd " + AppConfig["TmpDir"] + " ; bash " + AppConfig["TmpDir"] + "/" + FileName[AppName] + " " + AppConfig[
        "ScriptRun"]
    print("正在执行:" + tmpStr)
    command = [tmpStr]
    res = HostManager.SSH.SshComm(HostData["host"], HostData["port"], HostData["username"], HostData["password"], command)
    # 只可用于测试用，平常日志可不能这么简单的收集
    print(res[tmpStr])


def InitScript():
    print("初始化脚本、应用配置、安装列表到内存")
    Logs_views.log("初始化脚本、应用配置、安装列表到内存")
    LoadScript()
    LoadConfig()
    getInstalledList()


InitScript()
